﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.IO;

namespace IURIP.Tool
{
    public class Util
    {
        /// <summary>
        /// Gets XmlDocument instance from a string directly
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public static XmlDocument GetXmlDoc(string xmlString)
        {
            XmlDocument res = new XmlDocument();
            res.LoadXml(xmlString);
            return res;
        }
        public static XmlNode GetXmlNode(string xmlString)
        {
            XmlDocument res = GetXmlDoc(xmlString);
            if (res.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
            {
                res.RemoveChild(res.FirstChild);
            }
            return res.FirstChild;
        }
        public static string RemoveNameSpace(string originalXmlString)
        {
            string xslt = @"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
  <xsl:output method='xml' indent='no' omit-xml-declaration='yes'/>
  <xsl:template match='/|comment()|processing-instruction()'>
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match='*'>
    <xsl:element name='{local-name()}'>
      <xsl:apply-templates select='@*|node()'/>
    </xsl:element>
  </xsl:template>

  <xsl:template match='@*'>
    <xsl:attribute name='{local-name()}'>
      <xsl:value-of select='.'/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
";
            StringBuilder sb = new StringBuilder();
            XmlWriter xw = XmlWriter.Create(sb);
            XslCompiledTransform xsl = new XslCompiledTransform();

            xsl.Load(GetXmlReader(xslt));
            xsl.Transform(GetXmlReader(originalXmlString), xw);
            return sb.ToString();
        }
        public static XmlReader GetXmlReader(string xmlString)
        {
            StringReader sr = new StringReader(xmlString);
            return XmlReader.Create(sr);
        }
        /// <summary>
        /// Get child node of the parent node by name attribute
        /// </summary>
        /// <param name="parent">The parent node</param>
        /// <param name="childName">The name of the child</param>
        /// <returns></returns>
        public static XmlNode GetChildNode(XmlNode parent, string childName)
        {
            return GetXPathNode(parent, string.Format("./*[@name='{0}']", childName));
        }
        public static string GetChildValue(XmlNode parent, string name)
        {
            return GetXPathValue(parent, string.Format("./*[@name='{0}']/@value", name));
        }
        public static XmlNode GetXPathNode(XmlNode node, string xpath)
        {
            try
            {
                return node.SelectSingleNode(xpath);
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        public static string GetXPathValue(XmlNode node, string xpath)
        {
            XmlNode tmp = GetXPathNode(node, xpath);
            return tmp == null ? "" : tmp.NodeType == XmlNodeType.Attribute ? tmp.Value : tmp.InnerXml;
        }
        public static List<XmlNode> GetXPathList(XmlNode node, string xpath)
        {
            List<XmlNode> res = new List<XmlNode>();
            try
            {
                XmlNodeList nodeList = node.SelectNodes(xpath);
                for (int i = 0; i < nodeList.Count; i++)
                {
                    res.Add(nodeList[i]);
                }
            }
            catch
            {
            }
            return res;
        }
        public static List<string> GetListValues(XmlNode node, string name)
        {
            List<string> res = new List<string>();
            List<XmlNode> list = GetXPathList(node, string.Format("./listItem/field[@name='{0}']/@value", name));
            for (int i = 0; i < list.Count; i++)
            {
                res.Add(list[i].Value);
            }
            return res;
        }
        public static string GetListItemValue(XmlNode listItem, string name)
        {
            return Util.GetChildValue(listItem, name);
        }
        public static string GetAttributeValue(XmlNode node, string attributeName, bool trim)
        {
            string tmp = GetXPathValue(node, "./@" + attributeName);
            return trim ? tmp.Trim() : tmp;
        }
        public static bool GetAttributeBoolValue(XmlNode node, string attributeName, bool forceValue)
        {
            string v = GetAttributeValue(node, attributeName, true);
            return (v.ToLower() == forceValue.ToString().ToLower()) ? forceValue : !forceValue;
        }
        public static XmlNode CreateNode(XmlNode parent, string tagName, string name, string value)
        {
            XmlDocument doc = parent.OwnerDocument;
            XmlElement child = doc.CreateElement(tagName);
            parent.AppendChild(child);
            if (name != null)
            {
                XmlAttribute nameAtt = doc.CreateAttribute("name");
                nameAtt.Value = name;
                child.Attributes.Append(nameAtt);
            }
            if (value != null)
            {
                XmlAttribute valueAtt = doc.CreateAttribute("value");
                valueAtt.Value = value;
                child.Attributes.Append(valueAtt);
            }
            return child;
        }
        /// <summary>
        /// Creates new child node and appends the new node to the parent node
        /// </summary>
        /// <param name="parent">The parent node</param>
        /// <param name="name">The child node's name</param>
        /// <param name="value">The child node's value</param>
        /// <param name="isList">Indicates the child is list node or not</param>
        /// <param name="isSub">Indicates the child is sub node or not</param>
        /// <returns>The new child node</returns>
        public static XmlNode CreateNode(XmlNode parent, string name, string value, bool isList, bool isSub)
        {
            return CreateNode(parent, (isList ? (isSub ? "subList" : "list") : (isSub ? "subField" : "field")), name, value);
        }
        public static XmlNode CreateListItemNode(XmlNode parent)
        {
            return CreateNode(parent, "listItem", null, null);
        }
    }
}
